﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TaskFactory_When_FromAsync.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Threading
{
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Testing.Threading;

    [TestClass]
    public class TaskFactory_When_FromAsync : AsynchronousTest
    {
        private void RunTaskAndAssertLogEquals(ITask task, string expectedLog)
        {
            AsyncUtility.InvokeAndWait(eventHandle =>
                task.Start(t => eventHandle.Set()));
            Assert.AreEqual(expectedLog, Log.Text);
        }

        private T RunTaskAndAssertLogEquals<T>(ITask<T> task, string expectedLog)
        {
            AsyncUtility.InvokeAndWait(eventHandle =>
                task.Start(t =>
                    {
                        Log.AppendFormat(":{0}", t.Result);
                        eventHandle.Set();
                    }));
            Assert.AreEqual(expectedLog, Log.Text);
            return task.Result;
        }

        private EndAsyncMethod LoggingEndInvoke(Action<IAsyncResult> endInvoke)
        {
            return ar =>
                {
                    Log.Append("End()");
                    endInvoke(ar);
                };
        }

        private EndAsyncMethod<T> LoggingEndInvoke<T>(Func<IAsyncResult, T> endInvoke)
        {
            return ar =>
                {
                    Log.Append("End()");
                    return endInvoke(ar);
                };
        }

        [TestMethod]
        public void If_Action_With_0_Args()
        {
            Action action = () => Log.Append("Begin()");
            var task = Task.Factory.FromAsync(action.BeginInvoke,
                LoggingEndInvoke(action.EndInvoke));
            RunTaskAndAssertLogEquals(task, "Begin()End()");
        }

        [TestMethod]
        public void If_Action_With_1_Args()
        {
            Action<int> action = arg1 => Log.AppendFormat("Begin({0})", arg1);
            var task = Task.Factory.FromAsync(action.BeginInvoke,
                LoggingEndInvoke(action.EndInvoke), 10);
            RunTaskAndAssertLogEquals(task, "Begin(10)End()");
        }

        [TestMethod]
        public void If_Action_With_2_Args()
        {
            Action<int, string> action = (arg1, arg2) => Log.AppendFormat("Begin({0},{1})", arg1, arg2);
            var task = Task.Factory.FromAsync(action.BeginInvoke,
                LoggingEndInvoke(action.EndInvoke), 10, "String");
            RunTaskAndAssertLogEquals(task, "Begin(10,String)End()");
        }

        [TestMethod]
        public void If_Action_With_3_Args()
        {
            Action<int, string, double> action = (arg1, arg2, arg3) => Log.AppendFormat("Begin({0},{1},{2})", arg1, arg2, arg3);
            var task = Task.Factory.FromAsync(action.BeginInvoke,
                LoggingEndInvoke(action.EndInvoke), 10, "String", 10.5);
            RunTaskAndAssertLogEquals(task, "Begin(10,String,10.5)End()");
        }

        [TestMethod]
        public void If_Function_With_0_Args()
        {
            Func<int> func = () =>
                {
                    Log.Append("Begin()");
                    return 1;
                };
            var task = Task.Factory.FromAsync(func.BeginInvoke,
                LoggingEndInvoke<int>(func.EndInvoke));

            Assert.AreEqual(1, RunTaskAndAssertLogEquals(task, "Begin()End():1"));
        }

        [TestMethod]
        public void If_Function_With_1_Args()
        {
            Func<int, int> func = (arg1) =>
                {
                    Log.AppendFormat("Begin({0})", arg1);
                    return 1;
                };
            var task = Task.Factory.FromAsync(func.BeginInvoke,
                LoggingEndInvoke<int>(func.EndInvoke), 10);
            Assert.AreEqual(1, RunTaskAndAssertLogEquals(task, "Begin(10)End():1"));
        }

        [TestMethod]
        public void If_Function_With_2_Args()
        {
            Func<int, string, int> func = (arg1, arg2) =>
                {
                    Log.AppendFormat("Begin({0},{1})", arg1, arg2);
                    return 1;
                };
            var task = Task.Factory.FromAsync(func.BeginInvoke,
                LoggingEndInvoke<int>(func.EndInvoke), 10, "String");
            Assert.AreEqual(1, RunTaskAndAssertLogEquals(task, "Begin(10,String)End():1"));
        }

        [TestMethod]
        public void If_Function_With_3_Args()
        {
            Func<int, string, double, int> func = (arg1, arg2, arg3) =>
                {
                    Log.AppendFormat("Begin({0},{1},{2})", arg1, arg2, arg3);
                    return 1;
                };
            var task = Task.Factory.FromAsync(func.BeginInvoke,
                LoggingEndInvoke<int>(func.EndInvoke), 10, "String", 10.1);
            Assert.AreEqual(1, RunTaskAndAssertLogEquals(task, "Begin(10,String,10.1)End():1"));
        }
    }
}